package ca.cbc.medialib.service;

import ca.cbc.medialib.Bootstrap;
import ca.cbc.medialib.entity.Category;
import ca.cbc.medialib.entity.Sponsor;
import ca.cbc.medialib.exception.ThePlatformObjectNotFoundException;

import com.google.common.base.Function;
import com.theplatform.data.api.DataObjectField;
import com.theplatform.data.api.client.query.Query;
import com.theplatform.data.api.exception.ObjectNotFoundException;
import com.theplatform.data.api.objects.FieldInfo;
import com.theplatform.media.api.client.query.category.ByFullTitle;
import com.theplatform.media.api.client.query.category.ByParentId;
import com.theplatform.media.api.fields.CategoryField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * =============================================
 * Copyright (c) 2011 Canadian Broadcasting Corporation.
 * All rights reserved.
 * <p/>
 * ca.cbc.medialib.service.CategoryService.java
 * =============================================
 * <p/>
 * PURPOSE:	Manages communicate with thePlatform for Category
 * <p/>
 * =============================================
 * MODIFICATION		LOG	DATE		REASON / Change Request #
 * Liu Yang			Jun 22, 2011	Initial file creation
 * =============================================
 */

public class CategoryService extends EntityService {
    private Logger logger = LoggerFactory.getLogger(CategoryService.class);

    private static String[] fields = new String[]{
            CategoryField.fullTitle.toString(),
            DataObjectField.id.toString(),
            CategoryField.parentId.toString(),
            CategoryField.label.toString(),
            DataObjectField.title.toString(),
            DataObjectField.customValues.toString()
    };

    private Sponsor parseSponsor(String urlPipe, Category cat) {
        if (urlPipe == null || urlPipe.split("\\|").length != 2)
            return null;

        String[] strArray = urlPipe.split("\\|");
        return new Sponsor(strArray[0], strArray[1]);
    }

    public Function<com.theplatform.media.api.data.objects.Category, Category> convertCategory =
            new Function<com.theplatform.media.api.data.objects.Category, Category>() {
                @Override
                public Category apply(com.theplatform.media.api.data.objects.Category category) {
                    Category c = new Category(zeroOrLong(removePrefix(nullOrString(category.getId()))),
                            nullOrString(category.getTitle()),
                            nullOrString(category.getFullTitle()),
                            nullOrString(category.getCustomValue("mobile", "mobileDescription")),
                            nullOrString(category.getCustomValue("mobile", "mobileBigBoxURL")),
                            nullOrString(category.getCustomValue("mobile", "mobileBannerAdURL")),
                            nullOrString(category.getCustomValue("mobile", "mobileBannerAdURLForIPhone")),
                            nullOrString(category.getCustomValue("mobile", "mobileThumbnailURL")));

                    //add sortField and sortOrder here
                    String fieldNamespace = null;
                    for (FieldInfo field : category.getCustomValues().keySet()) {
                        if (field.getFieldName().equals("genre")) {
                            fieldNamespace = field.getNamespace();
                            break;
                        }
                    }
                    c.setSortOrder(nullOrString(category.getCustomValue(fieldNamespace, "sortOrder")));
                    c.setSortField(nullOrString(category.getCustomValue(fieldNamespace, "sortField")));
                    c.setGroupLevel(nullOrString(category.getCustomValue(fieldNamespace, "groupLevel")));
                    c.setGroupOrder(nullOrString(category.getCustomValue(fieldNamespace, "groupOrder")));

                    //add six sponsors here
                    for (int i = 1; i <= 6; i++) {
                        Sponsor s = parseSponsor(nullOrString(category.getCustomValue("mobile", "mobileSponsor" + i)), c);
                        if (s != null) {
                            c.addSponsor(s);
                        }
                    }
                    if (category.getParentId() != null && !category.getParentId().toString().trim().equals("")) {
                        try {
                            c.setParent(get(Long.valueOf(removePrefix(category.getParentId().toString()))));
                        } catch (ThePlatformObjectNotFoundException e) {
                            logger.error("Could not found parent category for " + category.getFullTitle());
                            throw new RuntimeException("Could not found parent category for " + category.getFullTitle(), e);
                        }
                    }

                    return c;
                }
            };

    public Category get(long id) throws ThePlatformObjectNotFoundException {
        if (id == 0l)
            return null;

        try {
            com.theplatform.media.api.data.objects.Category c = Bootstrap.instance.getCategoryClient().get(
                    new URI(String.valueOf(id)),
                    fields
            );
            Category cat = convertCategory.apply(c);

            return cat;
        } catch (URISyntaxException e) {
            throw new ThePlatformObjectNotFoundException("Category URI Syntex Error", e);
        } catch (ObjectNotFoundException e) {
            throw new ThePlatformObjectNotFoundException("Category object not found", e);
        }
    }

    public List<Category> findChildren(long id) throws ThePlatformObjectNotFoundException {
        try {
            List<com.theplatform.media.api.data.objects.Category> feed = Bootstrap.instance.getCategoryClient().getAll(
                    fields,
                    new Query[]{new ByParentId(new URI(String.valueOf(id)))},
                    null, null, false
            ).getEntries();
            return convertToCBCategories(feed);
        } catch (URISyntaxException e) {
            throw new ThePlatformObjectNotFoundException("Category URI Syntex Error", e);
        }
    }

    private List<Category> convertToCBCategories(List<com.theplatform.media.api.data.objects.Category> feed) {
        List<Category> result = new ArrayList<Category>();
        for (com.theplatform.media.api.data.objects.Category c : feed) {
            result.add(convertCategory.apply(c));
        }
        return result;
    }

    public Category findByFullTitle(String fullTitle) throws ThePlatformObjectNotFoundException {
        List<com.theplatform.media.api.data.objects.Category> feed = Bootstrap.instance.getCategoryClient().getAll(
                fields,
                new Query[]{new ByFullTitle(fullTitle)},
                null, null, false
        ).getEntries();

        Iterator<com.theplatform.media.api.data.objects.Category> itr = feed.iterator();

        if (!itr.hasNext()) {
            throw new ThePlatformObjectNotFoundException("Category object not found with full title " + fullTitle);
        }
        com.theplatform.media.api.data.objects.Category c = itr.next();
        if (itr.hasNext()) {
            logger.warn("More than one category with full title {}", c.getFullTitle());
        }
        return convertCategory.apply(c);
    }
}
